
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include "Command.h"

using namespace std;

namespace Server {
namespace Command {

int CCommandParam::GetInt()
{
	try {
		return boost::lexical_cast<int>(mRaw);
	}
	catch(std::exception&) {
		return -1;
	}
}

bool CCommandParser::NextToken(string& token) 
{
	if(mPos >= mData.length()) return false;
	while(mData[mPos] == ' ') mPos++;
	if(mPos >= mData.length()) return false;

	int pos2 = mData.find(' ', mPos);
	if(pos2 < 0) {
		token = mData.substr(mPos);
		mPos = mData.length() + 1;
	}
	else {
		token = mData.substr(mPos, pos2-mPos);
		mPos = pos2 + 1;
	}

	boost::algorithm::trim(token);
	return token.length() > 0;
}

CCommandTreeNode CCommandTreeNode::mCommandRoot;

CCommandTreeNode::CCommandTreeNode(string& key, CCommandParser& parser) :
	mKey(key), mHasParam(false), mAction(NULL)
{
	string token;
	while(1) {
		if(parser.NextToken(token)) {
			if(token[0] == '<') {
				mHasParam = true;
				continue;
			}

			AddChild(token, parser);
		}
		else {
			mAction = parser.GetAction();
		}

		break;
	}
}

CCommandTreeNode* CCommandTreeNode::FindChild(string& key)
{
	for(vector<CCommandTreeNode>::iterator iter = mChilds.begin(); iter != mChilds.end(); iter++) {
		if((*iter).Key() == key) {
			CCommandTreeNode& child = *iter;
			return &child;
		}
	}

	return NULL;
}

void CCommandTreeNode::AddChild(string& cmd, CCommandAction* action)
{
	CCommandParser parser(cmd, action);
	string token;
	if(parser.NextToken(token)) AddChild(token, parser);
}

void CCommandTreeNode::ParseAndExec(string& cmd, string& output)
{
	CCommandParser parser(cmd);
	Parse(parser);
	CCommandAction* action = parser.GetAction();
	if(action) action->DoAction(parser.Params(), output);
}

void CCommandTreeNode::AddChild(string& key, CCommandParser& parser)
{
	CCommandTreeNode* child = FindChild(key);
	if(child) {
		string token;
		while(parser.NextToken(token)) {
			if(token[0] != '<') {
				child->AddChild(token, parser);
				break;
			}
			else {
				child->HasParam() = true;
			}
		}
	}
	else {
		mChilds.push_back(CCommandTreeNode(key, parser));
	}
}

void CCommandTreeNode::Parse(CCommandParser& parser)
{
	string token;
	bool param_parsed = false;
	while(1) {
		if(parser.NextToken(token)) {
			if(mHasParam && !param_parsed) {
				parser.Params().push_back(CCommandParam(token));
				param_parsed = true;
				continue;
			}
			else {
				CCommandTreeNode* child = FindChild(token);
				if(child) child->Parse(parser);
				break;
			}
		}
		else {
			parser.SetAction(mAction);
		}

		break;
	}
}

} // Common
} // Command
